Imports System
Imports System.Text
Imports System.Data
Imports System.Collections.Generic
Imports System.Web
Imports System.IO

Imports Framework

'Collection Class (Customisable half)
Partial Public Class CFileList
        
#Region "Filters"
    Public ReadOnly Property Mp3s As CFileList
        Get
            Return GetByExtensionId(EExtension.Mp3)
        End Get
    End Property
    Public ReadOnly Property Htms As CFileList
        Get
            Return GetByExtensionId(EExtension.Html)
        End Get
    End Property
    Public ReadOnly Property PdfsOrWords As CFileList
        Get
            Return GetByExtensionId(EExtension.PdfOrWord)
        End Get
    End Property
    Public ReadOnly Property Mp4s As CFileList
        Get
            Return GetByExtensionId(EExtension.Mp4)
        End Get
    End Property
    Public ReadOnly Property Mobis As CFileList
        Get
            Return GetByExtensionId(EExtension.Mobi)
        End Get
    End Property
    Public ReadOnly Property Epubs As CFileList
        Get
            Return GetByExtensionId(EExtension.Epub)
        End Get
    End Property


#End Region

#Region "Aggregation"
    Public ReadOnly Property HasMp3 As Boolean
        Get
            Return Mp3s.Count > 0
        End Get
    End Property
    Public ReadOnly Property HasHtm As Boolean
        Get
            Return Htms.Count > 0
        End Get
    End Property
    Public ReadOnly Property HasPdfOrWord As Boolean
        Get
            Return PdfsOrWords.Count > 0
        End Get
    End Property
    Public ReadOnly Property HasMobi As Boolean
        Get
            Return Mobis.Count > 0
        End Get
    End Property
    Public ReadOnly Property HasEpub As Boolean
        Get
            Return Epubs.Count > 0
        End Get
    End Property


    Public ReadOnly Property FirstMp3 As CFile
        Get
            If Not HasMp3 Then Return Nothing
            Return Mp3s(0)
        End Get
    End Property
    Public ReadOnly Property FirstHtm As CFile
        Get
            If Not HasHtm Then Return Nothing
            Return Htms(0)
        End Get
    End Property
    Public ReadOnly Property FirstPdfOrWord As CFile
        Get
            If Not HasPdfOrWord Then Return Nothing
            Return PdfsOrWords(0)
        End Get
    End Property
    Public ReadOnly Property FirstMobi As CFile
        Get
            If Not HasMobi Then Return Nothing
            Return Mobis(0)
        End Get
    End Property
    Public ReadOnly Property FirstEpub As CFile
        Get
            If Not HasEpub Then Return Nothing
            Return Epubs(0)
        End Get
    End Property


    Public ReadOnly Property NamesAndSizes As String
        Get
            Dim sb As New StringBuilder
            For Each i As CFile In Me
                sb.AppendLine(i.FileNameAndSize)
            Next
            Return sb.ToString
        End Get
    End Property
    Public ReadOnly Property NamesAndSizesShort As String
        Get
            Dim sb As New StringBuilder
            For Each i As CFile In Me
                sb.AppendLine(i.FileNameAndSizeShort)
            Next
            Return sb.ToString
        End Get
    End Property

    Private m_namesNormalised As List(Of String) = Nothing
    Private m_namesDict As Dictionary(Of String, CFile) = Nothing
    Public ReadOnly Property NamesDict As Dictionary(Of String, CFile)
        Get
            If IsNothing(m_namesDict) Then
                Dim obj As Integer = NamesNormalised.Count
            End If
            Return m_namesDict
        End Get
    End Property
    Public ReadOnly Property NamesNormalised As List(Of String) 'All Backslashes, with no leading slash
        Get
            If IsNothing(m_namesNormalised) Then
                SyncLock (Me)
                    If IsNothing(m_namesNormalised) Then
                        Dim list As New List(Of String)(Me.Count)
                        Dim dict As New Dictionary(Of String, CFile)

                        For Each i As CFile In Me
                            Dim s As String = i.FileName.ToLower.Trim.Replace("/", "\")
                            If s.StartsWith("\") Then s = s.Substring(1)
                            list.Add(s)
                            dict(s) = i
                        Next

                        m_namesNormalised = list
                        m_namesDict = dict
                    End If
                End SyncLock
            End If
            Return m_namesNormalised
        End Get
    End Property
#End Region

#Region "Searching (Optional)"
    'Represents a simple search box to search PK and any string columns (add overloads as required, based on the pattern below)
    'e.g. Public Function Search(ByVal nameOrId As String, ByVal productId As Integer) As CFileList
    Public Function Search(ByVal nameOrId As String, extensionId As Byte?) As CFileList
        '1. Normalisation
        If IsNothing(nameOrId) Then nameOrId = String.Empty
        nameOrId = nameOrId.Trim.ToLower()

        '2. Start with a complete list
        Dim results As CFileList = Me

        '3. Use any available index, such as those generated for fk/bool columns
        'Normal Case - non-unique index (e.g. foreign key)
        If extensionId.HasValue Then results = results.GetByExtensionId(extensionId.Value)

        'Special case - unique index (e.g. primary key)
        If Not String.IsNullOrEmpty(nameOrId) Then
            Dim id As Integer
            If Integer.TryParse(nameOrId, id) Then
                Dim obj As CFile = Me.GetById(id)
                If Not IsNothing(obj) Then
                    results = New CFileList(1)
                    results.Add(obj)
                    Return results
                End If
            End If
        End If

        '4. Exit early if remaining (non-index) filters are blank
        If String.IsNullOrEmpty(nameOrId) Then Return results

        '5. Manually search each record using custom match logic, building a shortlist
        Dim shortList As New CFileList
        For Each i As CFile In results
            If Match(nameOrId, i) Then shortList.Add(i)
        Next
        Return shortList
    End Function
    'Manual Searching e.g for string-based columns i.e. anything not indexed (add more params if required)
    Private Function Match(ByVal name As String, ByVal obj As CFile) As Boolean
        If Not String.IsNullOrEmpty(name) Then
            If obj.FileName.ToLower().Contains(name) Then Return True
            If obj.Product.ProductName.ToLower().Contains(name) Then Return True
            Return False 'If filter is active, reject any items that dont match
        End If
        Return True 'No active filters (should catch this in step #4)
    End Function
#End Region

#Region "Cloning"
    Public Function Clone(ByVal target As CDataSrc) As CFileList ', parentId As Integer) As CFileList
        'No Transaction
        If TypeOf target Is CDataSrcRemote Then Return Clone(target, Nothing) ', parentId)

        'Transaction
        Dim cn As IDbConnection = target.Local.Connection()
        Dim tx As IDbTransaction = cn.BeginTransaction()
        Try
            Clone = Clone(target, tx) ', parentId)
            tx.Commit()
        Catch
            tx.Rollback()
            Throw
        Finally
            cn.Close()
        End Try
    End Function
    Public Function Clone(target as CDataSrc, txOrNull as IDbTransaction) As CFileList ', parentId As Integer) As CFileList
        Dim list As New CFileList(Me.Count)
        For Each i As CFile In Me
            list.Add(i.Clone(target, txOrNull))  ', parentId))    *Child entities must reference the new parent
        Next
        Return list
    End Function
#End Region

#Region "Export to Csv"
    'Web - Need to add a project reference to System.Web, or comment out these two methods
    Public Sub ExportToCsv(ByVal response As HttpResponse)
        ExportToCsv(response, "Files.csv")
    End Sub
    Public Sub ExportToCsv(ByVal response As HttpResponse, ByVal fileName As String)
        CDataSrc.ExportToCsv(response, fileName) 'Standard response headers
        Dim sw As New StreamWriter(response.OutputStream)
        ExportToCsv(sw)
        sw.Flush()
        response.End()
    End Sub

    'Non-web
    Public Sub ExportToCsv(ByVal filePath As String)
        Dim sw As New StreamWriter(filePath)
        ExportToCsv(sw)
        sw.Close()
    End Sub

    'Logic
    Protected Sub ExportToCsv(ByVal sw As StreamWriter)
        Dim headings As String() = New String() {"FileId", "FileProductId", "FileSize", "FileName"}
        CDataSrc.ExportToCsv(headings, sw)
        For Each i As CFile In Me
            Dim data As Object() = New Object() {i.FileId, i.FileProductId, i.FileSize, i.FileName}
            CDataSrc.ExportToCsv(data, sw)
        Next
    End Sub
#End Region

End Class
